/*
 * Copyright (c) 2010, Leon Dang f3it.com
 *           (c) 2010, Andrew Korolev redfox14 at gmail dot com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *   * Neither the name of the authors nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "mainwindow.h"
#include <QtGui>
#include <QtDBus>

#include "userdetails.h"
#include "smsdetails.h"
#include "dbrecord.h"
#include "dbrecords.h"
#include "settings.h"
#include "loadingwidget.h"
#include "version.h"

static QDBusMessage::QDBusMessage launchDBusApp(QString name)
{
	/* from http://forums.internettablettalk.com/showthread.php?p=860086:
	 *
	 * Launch phone application ( rtcom-call-ui.desktop ):
	 * dbus-send --type=method_call --dest=com.nokia.HildonDesktop.AppMgr /com/nokia/HildonDesktop/AppMgr com.nokia.HildonDesktop.AppMgr.LaunchApplication string:rtcom-call-ui
	 *
	 * Launch conversations application ( rtcom-messaging-ui.desktop ):
	 * dbus-send --type=method_call --dest=com.nokia.HildonDesktop.AppMgr /com/nokia/HildonDesktop/AppMgr com.nokia.HildonDesktop.AppMgr.LaunchApplication string:rtcom-messaging-ui
	 *
	 * Launch email application ( modest.desktop ):
	 * dbus-send --type=method_call --dest=com.nokia.HildonDesktop.AppMgr /com/nokia/HildonDesktop/AppMgr com.nokia.HildonDesktop.AppMgr.LaunchApplication string:modest
	 *
	 * Launch contacts application ( osso-addressbook.desktop ):
	 * dbus-send --type=method_call --dest=com.nokia.HildonDesktop.AppMgr /com/nokia/HildonDesktop/AppMgr com.nokia.HildonDesktop.AppMgr.LaunchApplication stringsso-addressbook
	 *
	 * Launch browser application ( browser.desktop ):
	 * dbus-send --type=method_call --dest=com.nokia.HildonDesktop.AppMgr /com/nokia/HildonDesktop/AppMgr com.nokia.HildonDesktop.AppMgr.LaunchApplication string:browser
	 */


	QDBusConnection bus = QDBusConnection::sessionBus();

	/* list all dbus services
	QStringList serviceNames = bus.interface()->registeredServiceNames();
	qDebug() << serviceNames;
	*/


	QDBusMessage message = QDBusMessage::createMethodCall("com.nokia.HildonDesktop.AppMgr",
														  "/com/nokia/HildonDesktop/AppMgr",
														  "com.nokia.HildonDesktop.AppMgr",
														  "LaunchApplication");
	QList<QVariant> mbusargs;
	mbusargs.append(name);
	message.setArguments(mbusargs);
	return bus.call(message);
}

MainWindow::MainWindow( QWidget * parent ): QMainWindow( parent )
{
	setWindowTitle( tr( WINDOW_TITLE ) );

	if ( ! readConfig() )
		qDebug() << "Error: Could not read the config file.";

#if defined( Q_WS_MAEMO_5 ) || defined( Q_WS_HILDON )
	setAttribute( m_screenOrientation, true );
#endif

	QFrame * frame = new QFrame();
	setCentralWidget( frame );
	frame->setEnabled( false );
	show();

#if defined( Q_WS_MAEMO_5 ) || defined( Q_WS_HILDON )
	setAttribute( Qt::WA_Maemo5ShowProgressIndicator, Qt::Checked );
#else
	setCursor( QCursor( Qt::BusyCursor ) );
#endif

	m_table = new QTableWidget( 0, 4, this );

	m_table->setSelectionMode( QAbstractItemView::SingleSelection );
	m_table->setSelectionBehavior( QAbstractItemView::SelectRows );
	m_table->setProperty( "FingerScrollable", true );
	m_table->horizontalHeader()->setDefaultSectionSize( 30 );
	m_table->horizontalHeader()->setResizeMode( 0, QHeaderView::Fixed );
	m_table->horizontalHeader()->setResizeMode( 1, QHeaderView::Stretch );
	m_table->horizontalHeader()->setResizeMode( 2, QHeaderView::Fixed );
	m_table->horizontalHeader()->setResizeMode( 3, QHeaderView::Fixed );
	m_table->verticalHeader()->hide();
	//table->setHorizontalHeaderLabels(QStringList() << tr("") << tr("") << tr("Name") << tr("Time"));
	m_table->horizontalHeader()->hide();

	// This affects all the cells in a QTableWidget
	m_table->setIconSize( QSize( 48, 48 ) );

	QBoxLayout * layout0 = new QBoxLayout( QBoxLayout::LeftToRight );
	layout0->setObjectName( "layout" );
	QIcon dial = QIcon::fromTheme( "call_dialpad_button", QIcon( IMG_DIAL ) );
	QPushButton * btnDial = new QPushButton( dial, tr( "Dialing pad" ), this->centralWidget() );
	QIcon contacts = QIcon::fromTheme( "general_contacts_button", QIcon( IMG_CONTACTS ) );
	QPushButton * btnContacts = new QPushButton( contacts, tr( "Select contact" ), this->centralWidget() );
	layout0->addWidget( btnDial );
	layout0->addWidget( btnContacts );


	LoadingWidget * lw = new LoadingWidget( m_screenOrientation, this );

	QBoxLayout * layout = new QBoxLayout( QBoxLayout::TopToBottom, frame );
	layout->addLayout( layout0 );
	layout->addWidget( lw );

	connect(btnDial, SIGNAL(clicked()), this, SLOT(launchDialApp()));
	connect(btnContacts, SIGNAL(clicked()), this, SLOT(launchContactApp()));

	connect( m_table, SIGNAL( itemClicked( QTableWidgetItem * ) ),
						this, SLOT( selectionMade( QTableWidgetItem * ) ) );
	connect( QApplication::desktop(), SIGNAL( resized( int ) ), this, SLOT( rotateWindow() ) );
	connect( m_DBRecords, SIGNAL( loaded() ), this, SLOT( populateTable() ) );
	connect( m_DBRecords, SIGNAL( avatarLoaded( int ) ), this, SLOT( updateAvatar( int ) ) );

	setupMenu();
	m_DBRecords->load();

	lw->close();
	layout->addWidget( m_table );
	frame->setEnabled( true );
}

void MainWindow::rotateWindow()
{
	QBoxLayout * layout = this->findChild< QBoxLayout * >( "layout" );
	if ( inPortraitMode() )
		layout->setDirection( QBoxLayout::TopToBottom );
	else
		layout->setDirection( QBoxLayout::LeftToRight );
	for ( int i = 0; i < m_DBRecords->count(); i++ )
	{
		QWidget * widget = m_table->cellWidget( i, 1 );
		QLabel * lbl = qobject_cast< QLabel * >( widget );
		if ( lbl )
		{
			QString text = generateLabelText( i );
			lbl->setText( text );
		}
	}
}

void MainWindow::populateTable()
{
#if defined( Q_WS_MAEMO_5 ) || defined( Q_WS_HILDON )
	setAttribute( Qt::WA_Maemo5ShowProgressIndicator, Qt::Checked );
#else
	setCursor( QCursor( Qt::BusyCursor ) );
#endif
	m_table->clear();
	m_table->setRowCount( 0 );

	for ( int i = 0; i < m_DBRecords->count(); i++ )
	{
		m_table->insertRow( i );

		QTableWidgetItem * qtiType = new QTableWidgetItem;
		QIcon iconType;
		QTableWidgetItem * qtiDirection = new QTableWidgetItem;
		QIcon iconDirection;

		EVENT_TYPE event = m_DBRecords->at( i )->recordType();

		switch ( event )
		{
			case ET_CALL:
			{
				CALL_TYPE ct = m_DBRecords->at( i )->callType();
				if ( ct == CT_SKYPE )
				{
					iconType = QIcon::fromTheme( "general_skype", QIcon( IMG_SKYPE ) );
				}
				else if ( ct == CT_GOOGLE )
				{
					iconType = QIcon::fromTheme( "general_gtalk", QIcon( IMG_GOOGLE ) );
				}
				else
				{
					iconType = QIcon::fromTheme( "call_status_cellular", QIcon( IMG_CELL ) );
				}
				switch ( m_DBRecords->at( i )->direction() )
				{
					case ED_INCOMING:
						iconDirection = QIcon::fromTheme( "general_received", QIcon( IMG_IN ) );
						break;
					case ED_OUTGOING:
						iconDirection = QIcon::fromTheme( "general_sent", QIcon( IMG_OUT ) );
						break;
					case ED_MISSED:
						iconDirection = QIcon::fromTheme( "general_missed", QIcon( IMG_MISSED ) );
						break;
				}
				break;
			}
			/* Not implemented now
			case ET_CHAT:
				qtiType->setIcon(  );
				break; */
			case ET_SMS:
				iconType = QIcon::fromTheme( "general_sms", QIcon( IMG_SMS_READ ) );
				if ( m_DBRecords->at( i )->isRead() )
				{
					if ( m_DBRecords->at( i )->direction() == ED_OUTGOING )
					{
						iconDirection = QIcon::fromTheme( "chat_replied_sms", QIcon( IMG_SMS_REPLIED ) );
					}
					else
					{
						iconDirection = QIcon::fromTheme( "general_sms", QIcon( IMG_SMS_READ ) );
					}
				}
				else
				{
					iconDirection = QIcon::fromTheme( "chat_unread_sms", QIcon( IMG_SMS_UNREAD ) );
				}
				break;
		}

		qtiType->setIcon( iconType );
		qtiDirection->setIcon( iconDirection );
//		qtiDirection->setFlags( qtiDirection->flags() & ~ ( Qt::ItemIsEditable ) );
//		qtiType->setFlags( qtiType->flags() & ~ ( Qt::ItemIsEditable ) );
		m_table->setItem( i, 0, qtiDirection );
		m_table->setItem( i, 2, qtiType );

		QString text = generateLabelText( i );
		QLabel * lbl = new QLabel( text, m_table );
		m_table->setCellWidget( i, 1, lbl );

		QTableWidgetItem * qti = new QTableWidgetItem;
		QString s = QString( m_DBRecords->at( i )->name() );

		qti->setIcon( m_DBRecords->at( i )->avatar() );
		m_table->setItem( i, 3, qti );
	}

	m_table->resizeRowsToContents();
	m_table->resizeColumnsToContents();
#if defined( Q_WS_MAEMO_5 ) || defined( Q_WS_HILDON )
	setAttribute( Qt::WA_Maemo5ShowProgressIndicator, Qt::Unchecked );
#else
	setCursor( QCursor( Qt::ArrowCursor ) );
#endif
}

QString MainWindow::generateLabelText( const int row )
{
	QString text;

	if ( m_DBRecords->at( row )->name() == m_DBRecords->at( row )->phoneNumber() )
	{
		if ( m_DBRecords->at( row )->name() == "" )
		{
			text = QString( "<font size=4>%1</font>").arg( tr( "Unknown" ) );
		} else
		{
			text = QString( "<font size=4>%1</font>" ).arg( m_DBRecords->at( row )->name() );
		}
	}
	else
	{
		text = QString( "<font size=4>%1</font>" ).arg( m_DBRecords->at( row )->name() );
		if ( ! inPortraitMode() )
			text.append( QString( "<font size=1> (%1)</font>" ).arg( m_DBRecords->at( row )->phoneNumber() ) );
	}
	text.append( "<br><font size=2>" );
	if ( m_DBRecords->at( row )->startDate() < QDate::currentDate() )
	{
		text.append( m_DBRecords->at( row )->startDate().toString( m_dateFormat ) );
		text.append( " " );
	}
	text.append( m_DBRecords->at( row )->startTime().toString( Qt::SystemLocaleShortDate ) );


	text.append( " | " );

	EVENT_TYPE et = m_DBRecords->at( row )->recordType();
	if ( et == ET_CALL)
	{
		if ( ! inPortraitMode() )
			text.append( tr( "Duration: " ) );
		text.append( m_DBRecords->at( row )->callDuration() );
	}
	else if ( et == ET_SMS )
	{
		if ( m_DBRecords->at( row )->endDateTime().toTime_t() == 0 )
		{
			// Seems like a database issue; SMS-outs do occur ok.
			//text.append( "<b>Not Delivered<b>" );
			text.append( tr( "Sent" ) );
		}
		else
		{
			if ( ! inPortraitMode() )
				text.append( tr( "Delivered on " ) );

			text.append( m_DBRecords->at( row )->endDate().toString( m_dateFormat ) );
			if ( m_DBRecords->at( row )->endDate() < QDate::currentDate() )
			{
				text.append( " " );
				text.append( m_DBRecords->at( row )->endTime().toString( Qt::SystemLocaleShortDate ) );
			}
		}
	}
	return text;
}

void MainWindow::updateAvatar( int index )
{
	QTableWidgetItem * qti = m_table->item( index, 3 );
	qti->setIcon( m_DBRecords->at( index )->avatar() );
}

void MainWindow::selectionMade( QTableWidgetItem * item )
{
	const DBRecord * dr = m_DBRecords->at( item->row() );
	if ( ! dr || ( dr->name() == "" && dr->phoneNumber() == "" ) )
		return;

	QString name = QString( dr->name() );
	QString phone = QString( dr->phoneNumber() );
	if ( dr->recordType() == ET_CALL )
	{
		UserDetails * ud = new UserDetails( dr, m_screenOrientation, this );
		ud->show();
	}
	else if ( dr->recordType() == ET_SMS )
	{
		SMSDetails * sd = new SMSDetails(dr, m_screenOrientation, this);
		sd->show();
		// To be implemented
	}
}


void MainWindow::launchDialApp()
{
	launchDBusApp("rtcom-call-ui");
}

void MainWindow::launchContactApp()
{
	launchDBusApp("osso-addressbook");
}

bool MainWindow::inPortraitMode() const
{
	// In portrait mode the width of the screen is narrower than its height.
	QRect rect = QApplication::desktop()->screenGeometry();
	return ( rect.width() < rect.height() );
}

bool MainWindow::readConfig()
{
	QString configFile = QDir::homePath () + CONFIG;
	QSettings settings( configFile, QSettings::IniFormat );
	int i;
#if defined( Q_WS_MAEMO_5 ) || defined( Q_WS_HILDON )
	i = settings.value( "Windows/Screen Orientation", ( int ) Qt::WA_Maemo5AutoOrientation ).toInt();
	m_screenOrientation = ( Qt::WidgetAttribute ) i;
#endif
	int maxRecords;
	maxRecords = settings.value( "Filter/Maximum Records", 100 ).toInt();

	i = settings.value( "Filter/Filter Options", ( int ) ( OptionsClass::ShowCalls |
										OptionsClass::ShowSMS | OptionsClass::ShowAll ) ).toInt();
	OptionsClass::FilterOption opt;
	opt = ( OptionsClass::FilterOption ) i;

	m_DBRecords = new DBRecords( opt, maxRecords, this );

	m_dateFormat = settings.value( "Table/Date Format", "ddd MMM d yy" ).toString();

	bool result = ! settings.status();
	return result;
}

bool MainWindow::saveConfig() const
{
	QString configFile = QDir::homePath () + CONFIG;
	QSettings settings( configFile, QSettings::IniFormat );
	bool result = settings.isWritable();
	if ( result )
	{
		int i;
#if defined( Q_WS_MAEMO_5 ) || defined( Q_WS_HILDON )
		i = ( int )m_screenOrientation;
		settings.setValue( "Windows/Screen Orientation", i );
#endif
		settings.setValue( "Filter/Maximum Records", m_DBRecords->maxRecords() );
		i = ( int )m_DBRecords->filterOptions();
		settings.setValue( "Filter/Filter Options", i );

		settings.setValue( "Table/Date Format", m_dateFormat );
	}
	return result;
}

void MainWindow::setupMenu()
{
	QActionGroup * grpTypeFilter = new QActionGroup( this );
	grpTypeFilter->setExclusive( true );
	grpTypeFilter->setObjectName( "grpTypeFilter" );

	QAction * actAllEvents = new QAction( tr( "All Events" ), grpTypeFilter );
	actAllEvents->setCheckable( true );
	actAllEvents->setObjectName( "All Events" );

	QAction * actCalls = new QAction( tr( "Calls" ), grpTypeFilter );
	actCalls->setCheckable( true );
	actCalls->setObjectName( "Calls" );

	QAction * actSMS = new QAction( tr( "SMS" ), grpTypeFilter );
	actSMS->setCheckable( true );
	actSMS->setObjectName( "SMS" );

	QActionGroup * grpDirectionFilter = new QActionGroup( this );
	grpDirectionFilter->setExclusive( true );
	grpDirectionFilter->setObjectName( "grpDirectionFilter" );

	QAction * actAllDirections = new QAction( tr( "All" ), grpDirectionFilter );
	actAllDirections->setCheckable( true );
	actAllDirections->setObjectName( "All Directions" );

	QAction * actIncoming = new QAction( tr( "In" ), grpDirectionFilter );
	actIncoming->setCheckable( true );
	actIncoming->setObjectName( "Incoming" );

	QAction * actOutgoing = new QAction( tr( "Out" ), grpDirectionFilter );
	actOutgoing->setCheckable( true );
	actOutgoing->setObjectName( "Outgoing" );

	QAction * actMissed = new QAction( "Missed", grpDirectionFilter );
	actMissed->setCheckable( true );
	actMissed->setObjectName( "Missed" );
	if ( m_DBRecords->filterOptions().testFlag( OptionsClass::ShowCalls ) )
	{
		if ( m_DBRecords->filterOptions().testFlag( OptionsClass::ShowSMS ) )
			actAllEvents->setChecked( true );
		else
			actCalls->setChecked( true );

		if ( m_DBRecords->filterOptions().testFlag( OptionsClass::ShowMissed ) )
				actMissed->setChecked( true );
	}
	else if ( m_DBRecords->filterOptions().testFlag( OptionsClass::ShowSMS ) )
	{
		actSMS->setChecked( true );
		actMissed->setVisible( true );
	}

	if ( m_DBRecords->filterOptions().testFlag( OptionsClass::ShowAll ) )
		actAllDirections->setChecked( true );
	else if ( m_DBRecords->filterOptions().testFlag( OptionsClass::ShowIncoming ) )
		actIncoming->setChecked( true );
	else if ( m_DBRecords->filterOptions().testFlag( OptionsClass::ShowOutgoing ) )
		actOutgoing->setChecked( true );

	menuBar()->addActions( grpTypeFilter->actions() );
	connect( actAllEvents, SIGNAL( triggered() ), this, SLOT( eventFilterChanged() ) );
	connect( actCalls, SIGNAL( triggered() ), this, SLOT( eventFilterChanged() ) );
	connect( actSMS, SIGNAL( triggered() ), this, SLOT( eventFilterChanged() ) );

	menuBar()->addActions( grpDirectionFilter->actions() );
	connect( actAllDirections, SIGNAL( triggered() ), this, SLOT( directionFilterChanged() ) );
	connect( actIncoming, SIGNAL( triggered() ), this, SLOT( directionFilterChanged() ) );
	connect( actOutgoing, SIGNAL( triggered() ), this, SLOT( directionFilterChanged() ) );
	connect( actMissed, SIGNAL( triggered() ), this, SLOT( directionFilterChanged() ) );

#if defined( Q_WS_MAEMO_5 ) || defined( Q_WS_HILDON )
	QAction * actOrientation = menuBar()->addAction( tr( "Turn Control" ) );
	connect( actOrientation, SIGNAL( triggered() ), this, SLOT( turnControlDlg() ) );
#endif

	QAction * actDateFormat = menuBar()->addAction( tr( "Date Format" ) );
	connect( actDateFormat, SIGNAL( triggered() ), this, SLOT( dateFormatDlg() ) );

	QAction * actMaxRecords = menuBar()->addAction( tr( "Records Limit" ) );
	connect( actMaxRecords, SIGNAL( triggered() ), this, SLOT( maxRecordsDlg() ) );

	QAction * actRefresh = menuBar()->addAction( tr( "Refresh" ) );
	connect( actRefresh, SIGNAL( triggered() ), m_DBRecords, SLOT( load() ) );

	QAction * actAbout = menuBar()->addAction( tr( "About" ) );
	connect( actAbout, SIGNAL( triggered() ), this, SLOT( aboutDlg() ) );
}

void MainWindow::aboutDlg() const
{
	QMessageBox msgBox;
	msgBox.setText( QString( tr( "<font size=4>Mcalllog version %1<br></font>"
							 "<font size=3>This is a Qt application that delivers a more featured "
							 "call log viewer for the n900 and other Maemo5 platforms.<br><br>"
							 "Website: <a href=\"http://code.google.com/p/maemocalllogviewer\">http://code.google.com/p/maemocalllogviewer</a><br><br></font>"
							 "<font size=1>Copyright © 2010, <a href=\"http://f3it.com\">Leon Dang</a><br>"
							 "Copyright © 2010, <a href=\"mailto:redfox14@gmail.com\">Andrew Korolev</a><br>"
							 "\tAll rights reserved.</font>" ) ).arg( APP_VERSION ) );
	msgBox.exec();
}
void MainWindow::dateFormatDlg()
{
	QBoxLayout::Direction direction;
//	if ( inPortraitMode() )
//		direction = QBoxLayout::LeftToRight;
//	else
		direction = QBoxLayout::TopToBottom;

	QDialog * dlg = new QDialog( this );
#if defined( Q_WS_MAEMO_5 ) || defined( Q_WS_HILDON )
	dlg->setAttribute( m_screenOrientation, true );
#endif
	dlg->setAttribute( Qt::WA_DeleteOnClose );
	dlg->setWindowTitle( tr( "Date Format" ) );

	QComboBox * combo = new QComboBox( dlg );
	combo->setObjectName( "ComboBox" );
	QDate date = QDate::currentDate();
	combo->addItem( date.toString( m_dateFormat ), QVariant( m_dateFormat ) );
	if ( m_dateFormat != FORMAT0 )
		combo->addItem( date.toString( FORMAT0 ), QVariant( FORMAT0 ) );
	if ( m_dateFormat != FORMAT1 )
		combo->addItem( date.toString( FORMAT1 ), QVariant( FORMAT1 ) );
	if ( m_dateFormat != FORMAT2 )
		combo->addItem( date.toString( FORMAT2 ), QVariant( FORMAT2 ) );
	if ( m_dateFormat != FORMAT3 )
		combo->addItem( date.toString( FORMAT3 ), QVariant( FORMAT3 ) );
	if ( m_dateFormat != FORMAT4 )
		combo->addItem( date.toString( FORMAT4 ), QVariant( FORMAT4 ) );
	if ( m_dateFormat != FORMAT5 )
		combo->addItem( date.toString( FORMAT5 ), QVariant( FORMAT5 ) );
	if ( m_dateFormat != FORMAT6 )
		combo->addItem( date.toString( FORMAT6 ), QVariant( FORMAT6 ) );

	QPushButton * btnSave = new QPushButton( tr( "Save" ), dlg );
	connect( btnSave, SIGNAL( clicked() ), this, SLOT( dateFormatChanged() ) );


	QBoxLayout * layout = new QBoxLayout( direction, dlg );
	layout->addWidget( combo, 2 );
	layout->addWidget( btnSave );

	dlg->exec();
}

void MainWindow::maxRecordsDlg()
{
	QBoxLayout::Direction direction;
//	if ( inPortraitMode() )
//		direction = QBoxLayout::LeftToRight;
//	else
	direction = QBoxLayout::TopToBottom;

	QDialog * dlg = new QDialog( this );
#if defined( Q_WS_MAEMO_5 ) || defined( Q_WS_HILDON )
	dlg->setAttribute( m_screenOrientation, true );
#endif
	dlg->setAttribute( Qt::WA_DeleteOnClose );
	dlg->setWindowTitle( tr( "Maximum Number of Records" ) );

	QSpinBox * spnMaxRecords = new QSpinBox( dlg );
	spnMaxRecords->setObjectName( "spnMaxRecords" );
	spnMaxRecords->setRange( 0, 1000 );
	spnMaxRecords->setValue( m_DBRecords->maxRecords() );

	QPushButton * btnSave = new QPushButton( tr( "Save" ), dlg );
	connect( btnSave, SIGNAL( clicked() ), this, SLOT( maxRecordsChanged() ) );

	QBoxLayout * layout = new QBoxLayout( direction, dlg );
	layout->addWidget( spnMaxRecords, 2 );
	layout->addWidget( btnSave );

	dlg->setLayout( layout );
	dlg->exec();
}

#if defined( Q_WS_MAEMO_5 ) || defined( Q_WS_HILDON )
void MainWindow::turnControlDlg()
{
	QBoxLayout::Direction direction;
//	if ( inPortraitMode() )
//		direction = QBoxLayout::LeftToRight;
//	else
	direction = QBoxLayout::TopToBottom;
	QDialog * dlg = new QDialog( this );
#if defined( Q_WS_MAEMO_5 ) || defined( Q_WS_HILDON )
	dlg->setAttribute( m_screenOrientation, true );
#endif
	dlg->setAttribute( Qt::WA_DeleteOnClose );
	dlg->setWindowTitle( tr( "Display Orientation" ) );
	dlg->setWindowModality( Qt::WindowModal );

	QButtonGroup * group = new QButtonGroup( dlg );
	group->setExclusive( true );

	QPushButton * btnAuto = new QPushButton( "Auto", dlg );
	btnAuto->setObjectName( "btnAuto" );
	btnAuto->setCheckable( true );
	group->addButton( btnAuto );
	connect( btnAuto, SIGNAL( clicked() ), this, SLOT( turnControlChanged() ) );

	QPushButton * btnLandscape = new QPushButton( tr( "Landscape" ), dlg );
	btnLandscape->setCheckable( true );
	btnLandscape->setObjectName( "btnLandscape" );
	group->addButton( btnLandscape );
	connect( btnLandscape, SIGNAL( clicked() ), this, SLOT( turnControlChanged() ) );

	QPushButton * btnPortrait = new QPushButton( tr( "Portrait" ), dlg );
	btnPortrait->setCheckable( true );
	btnPortrait->setObjectName( "btnPortrait" );
	group->addButton( btnPortrait );
	connect( btnPortrait, SIGNAL( clicked() ), this, SLOT( turnControlChanged() ) );

	switch ( m_screenOrientation )
	{
		case Qt::WA_Maemo5AutoOrientation:
			btnAuto->setChecked( true );
			break;
		case Qt::WA_Maemo5LandscapeOrientation:
			btnLandscape->setChecked( true );
			break;
		case Qt::WA_Maemo5PortraitOrientation:
			btnPortrait->setChecked( true );
			break;
		default:
			// capture compile warnings for others.
			break;
	}

	QBoxLayout * layout = new QBoxLayout( direction, dlg );
	layout->addWidget( btnAuto );
	layout->addWidget( btnLandscape );
	layout->addWidget( btnPortrait );
//	layout->addStretch();

//	QPushButton * btnSave = new QPushButton( "Save", dlg );
//	connect( btnSave, SIGNAL( pressed() ), this, SLOT( turnControlChanged() ) );

//	QBoxLayout * layout1 = new QBoxLayout( direction );
//	layout1->addStretch();
//	layout1->addWidget( btnSave );

//	direction = ( direction == QBoxLayout::TopToBottom ? QBoxLayout::LeftToRight: QBoxLayout::TopToBottom );
//	QBoxLayout * layout = new QBoxLayout( direction, dlg  );
//	layout->addLayout( layout0, 2 );
//	layout->addLayout( layout1 );
	dlg->setLayout( layout );
	dlg->exec();
}
#endif

void MainWindow::dateFormatChanged()
{
	if ( sender() )
	{
		QObject * parent = sender()->parent();
		if ( parent )
		{
			QComboBox * combo  = parent->findChild<QComboBox *>( "ComboBox" );
			QString format = combo->itemData( combo->currentIndex() ).toString();
			if ( format != m_dateFormat )
			{
				m_dateFormat = format;
				populateTable();
			}
		}
		QDialog * dlg = qobject_cast< QDialog * >( parent );
		if ( dlg )
			dlg->close();
	}
}

void MainWindow::eventFilterChanged()
{
	if ( sender() )
	{
		QActionGroup * grp = findChild<QActionGroup *>( "grpDirectionFilter" );
		QAction * act = grp->findChild< QAction * >( "Missed" );
		QString name = sender()->objectName();
		QString wtitle = QString("%1 - %2").arg(WINDOW_TITLE).arg(name);
		setWindowTitle( wtitle );
		if ( name == "All Events" )
		{
			m_DBRecords->setEventFilter( OptionsClass::ShowCalls | OptionsClass::ShowSMS );
			act->setVisible( true );
		}
		else if ( name == "Calls" )
		{
			m_DBRecords->setEventFilter( OptionsClass::ShowCalls );
			act->setVisible( true );
		}
		else if ( name == "SMS" )
		{
			m_DBRecords->setEventFilter( OptionsClass::ShowSMS );
			act->setVisible( false );
		}
	}
}

void MainWindow::directionFilterChanged()
{
	if ( sender() )
	{
		QString name = sender()->objectName();
		if ( name == "All Directions" )
			m_DBRecords->setDirectionFilter( OptionsClass::ShowAll );
		else if ( name == "Incoming" )
			m_DBRecords->setDirectionFilter( OptionsClass::ShowIncoming );
		else if ( name == "Outgoing" )
			m_DBRecords->setDirectionFilter( OptionsClass::ShowOutgoing );
		else if ( name == "Missed" ) {
			m_DBRecords->setDirectionFilter( OptionsClass::ShowMissed );
		}
	}
}

void MainWindow::maxRecordsChanged()
{
	if ( sender() )
	{
		QWidget * dlg = qobject_cast< QWidget * >( sender()->parent() );
		if ( dlg )
		{
			QSpinBox * spn = dlg->findChild< QSpinBox * >( "spnMaxRecords" );
			if ( spn )
			{

				m_DBRecords->setMaxRecords( spn->value() );
			}
			else
				qDebug() << "Error: Could not find the child called \"spnMaxRecords\"";

			dlg->close();
		}
		else
			qDebug() << "Error: Could not find the parent widget.";
	}
}

#if defined( Q_WS_MAEMO_5 ) || defined( Q_WS_HILDON )
void MainWindow::turnControlChanged()
{
	if ( sender() )
	{
		setAttribute( m_screenOrientation, false );
		QString name = sender()->objectName();
		if ( name == "btnAuto" )
			m_screenOrientation = Qt::WA_Maemo5AutoOrientation;
		else if ( name == "btnLandscape" )
			m_screenOrientation = Qt::WA_Maemo5LandscapeOrientation;
		else if ( name == "btnPortrait" )
			m_screenOrientation = Qt::WA_Maemo5PortraitOrientation;

		setAttribute( m_screenOrientation, true );
		QDialog * dlg = qobject_cast< QDialog * >( sender()->parent() );
		if ( dlg )
			dlg->close();
		else
			qDebug() << "turnControlChanged: Could not find the parent QDialog.";
	}
}
#endif

void MainWindow::closeEvent( QCloseEvent * event )
{

	if ( ! saveConfig() )
		qDebug() << "Error: Could not save the config file.";

	event->accept();
}

MainWindow::~MainWindow()
{
	delete m_DBRecords;
}
